﻿using Pay.Core;
using Pay.Data;
using Pay.DTO;
using Pay.TO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Pay.IService;

namespace Pay.Service {
    public class MallBillService : ServiceBase2 {
        protected IMerchantService _iMerchantService;
        protected ISettingService _iSettingService;
        protected IProductService _productService;

        public MallBillService(IUnitOfWork unitOfWork, IMerchantService iMerchantService,
                                ISettingService isettingService, IProductService productService) : base(unitOfWork) {
            _iMerchantService = iMerchantService;
            _iSettingService = isettingService;
            _productService = productService;
        }

        private DateTime _billDt;
        private Dictionary<string, Bill> _merchant_accounts;
        public List<message_push_dto> messages = new List<message_push_dto>();
        protected List<Profit> ProfiTables = new List<Profit>();

        /// <summary>
        /// 新增商户账务,处理好不要重复新增相同用户的账单
        /// </summary>
        /// <param name="merchant_id"></param>
        /// <returns></returns>
        private Bill AddMerchantBill(long merchant_id) {
            string key = merchant_id.ToString();
            Bill account;
            if (_merchant_accounts.TryGetValue(key, out account))
                return account;
            account = context.Bills.Where(c => c.MerchantId == merchant_id).FirstOrDefault();
            if (account == null) {
                account = new Bill();
                account.MerchantId = merchant_id;
                context.Bills.Add(account);
                _merchant_accounts.Add(key, account);
            } else {
                _merchant_accounts.Add(key, account);
            }

            return account;
        }
        /// <summary>
        /// token商城账单
        /// </summary>
        /// <param name="order"></param>
        /// <param name="binds"></param>
        /// <param name="busType">业绩类型：UpGrade：升级创客，Mall：商城购买</param>
        protected void TokenMallProfitAccount(Order order, List<bind_merchant_item> binds, TO.BusType busType = BusType.None) {
            _billDt = DateTime.Now;
            _merchant_accounts = new Dictionary<string, Bill>();
            foreach (var bind in binds) {
                AddTokenMallProfitAccount(order, bind, busType);
            }
        }
        /// <summary>
		/// 卖家货款
		/// </summary>
		protected void AddSellerAccount(Charge charge, Order order) {
            _merchant_accounts = new Dictionary<string, Bill>();
            var amount = order.Amount + order.Freight;
            context.Profits.Add(new Profit {
                OrderId = order.Id,
                MerchantId = order.MerchantId,
                Amount = amount,
                PayId = charge.PayId,
                ProductId = order.OrderItems.FirstOrDefault().ProductId,
                SkuId = order.OrderItems.FirstOrDefault().SkuId,
                BillType = BillType.Mall,
                BillStatus = BillStatus.Proceed,
                CreateTime = DateTime.Now.ToUnix()
            });
            var account = AddMerchantBill(order.MerchantId);
            account.Balance += amount;
            account.GoodsUnconfirmed += amount;
        }
        /// <summary>
        /// 卖家货款
        /// </summary>
        protected void AddSellerAccount(Order order) {
            _merchant_accounts = new Dictionary<string, Bill>();
            if (order.Amount <= 0) return;
            var profit = new Profit {
                OrderId = order.Id,
                MerchantId = order.MerchantId,
                Amount = order.Amount,
                PayId = order.PayId,
                ProductId = order.OrderItems.FirstOrDefault().ProductId,
                SkuId = order.OrderItems.FirstOrDefault().SkuId,
                BillType = BillType.Mall,
                BillStatus = BillStatus.Proceed,
                CreateTime = DateTime.Now.ToUnix(),
                Version = 1
            };
            bool is_active = order.OrderItems.Any(c => c.ActiveType == 1);
            if (is_active)
                profit.BillStatus = BillStatus.Finish;
            context.Profits.Add(profit);
            var account = AddMerchantBill(order.MerchantId);
            account.Balance += order.Amount;
            if (is_active)
                account.GoodsDeposit += order.Amount;
            else
                account.GoodsUnconfirmed += order.Amount;
        }
        /// <summary>
		/// 分销分润或积分抵扣
		/// </summary>
		/// <param name="charge">Charge.</param>
		/// <param name="profit">Profit.</param>
		private void AddMallProfitAccount(Charge charge, order_dto order, bind_merchant_item profit) {
            var billDetail = new BillDetail();
            billDetail.CreateTime = _billDt.ToUnix();
            if (charge.PayId.HasValue)
                billDetail.PayId = charge.PayId.Value;
            else
                billDetail.PayInfo = charge.PayInfo;
            billDetail.Amount = profit.amount;
            billDetail.BillType = BillType.Distribution;
            if (profit.amount < 0)
                billDetail.BillType = BillType.IntPay;
            if (order.status == OrderStatus.Finish)
                billDetail.Status = BillStatus.Finish;
            else
                billDetail.Status = BillStatus.Proceed;

            #region ef
            var merchant = _iMerchantService.Get(profit.merchant_no);
            var account = AddMerchantBill(merchant.id);
            account.Balance += billDetail.Amount;
            if (profit.freeze)
                account.Unconfirmed += billDetail.Amount;
            else
                account.Deposit += billDetail.Amount;
            billDetail.Bill = account;
            billDetail.Balance = account.Balance;
            context.BillDetails.Add(billDetail);
            #endregion
            var setting = _iSettingService.Get();
            var msgSetting = setting.msg.First(c => c.code == "profit");
            var msg = string.Format(msgSetting.content, profit.product_name, profit.amount.RoundDown(2));
            var model = new MessagePush();
            model.MerchantId = merchant.id;
            if (merchant.usertype.HasValue && merchant.usertype.Value == UserType.user) {
                model.Type = MsgType.OrderProft398;
                var product = _productService.GetForActicity(profit.product_id);
                if (product.distribution_price.HasValue) {
                    msg += string.Format("如果您是创客会员这次购物将获得{0}元佣金，立即升级为创客！", (product.distribution_price.Value * 0.5M).RoundDown(2));
                    model.Url = t_RequestMethod.token_url + "producttokenmaker";
                }
            } else
                model.Type = MsgType.OrderProft;
            model.Title = msgSetting.name;
            model.ShortContent = msg;
            model.Content = msg;
            model.Ext = "{}";
            model.CreateTime = DateTime.Now.ToUnix();
            model.ObjectId = order.id;
            context.MessagePushs.Add(model);
            messages.Add(model.ToDtoObject<message_push_dto>());
        }

        private void AddTokenMallProfitAccount(Order order, bind_merchant_item bind, TO.BusType busType) {
            var merchant = context.Merchants.FirstOrDefault(c => c.MerchantNo == bind.merchant_no);
            _merchant_accounts = new Dictionary<string, Bill>();
            _billDt = DateTime.Now;
            var profit = new Profit();
            profit.CreateTime = _billDt.ToUnix();
            profit.PayId = order.PayId;
            profit.OrderId = order.Id;
            profit.ProductId = bind.product_id;
            profit.SkuId = bind.sku_id;
            profit.Amount = bind.amount;
            profit.MerchantId = merchant.Id;
            profit.BillType = BillType.Distribution;
            profit.BillStatus = BillStatus.Proceed;
            profit.Version = 1;
            profit.IsBus = bind.is_bus;
            profit.TokenBillType = (busType == BusType.UpGrade ? TokenBillType.MarkBill : TokenBillType.DistributionBill);
            if (busType == BusType.UpGrade)
                profit.BillStatus = BillStatus.Finish;
            ProfiTables.Add(profit);
            if (bind.is_bus) {
                var bill = context.TokenStatistics.FirstOrDefault(c => c.MerchantId == merchant.Id);
                if (bill == null) {
                    bill = new TokenStatistics {
                        MerchantId = merchant.Id,
                        ConfirmProfit = bind.amount,
                        CreateTime = _billDt.ToUnix()
                    };
                    if (busType == BusType.UpGrade)
                        bill.BusDeposit = (bill.BusDeposit ?? 0) + bind.amount;
                    else
                        bill.FrozenBusProfit = (bill.FrozenBusProfit ?? 0) + bind.amount;
                    context.TokenStatistics.Add(bill);
                } else {
                    if (busType == BusType.UpGrade)
                        bill.BusDeposit = (bill.BusDeposit ?? 0) + bind.amount;
                    else
                        bill.FrozenBusProfit = (bill.FrozenBusProfit ?? 0) + bind.amount;
                    bill.ConfirmProfit += bind.amount;
                }
            } else {
                var account = AddMerchantBill(merchant.Id);
                account.Balance += bind.amount;
                if (busType == BusType.UpGrade)
                    account.Deposit += bind.amount;
                else
                    account.Unconfirmed += bind.amount;
            }
            //只推送分润佣金，业绩分润不推送。
            if (!bind.is_bus) {
                var setting = _iSettingService.Get();
                var msgSetting = setting.msg.First(c => c.code == "profit");
                var msg = string.Format(msgSetting.content, bind.product_name, bind.amount.RoundDown(2));
                var model = new MessagePush();
                model.MerchantId = merchant.Id;
                model.Type = MsgType.OrderProft;
                model.Title = msgSetting.name;
                model.ShortContent = msg;
                model.Content = msg;
                model.Ext = "{}";
                model.CreateTime = _billDt.ToUnix();
                model.ObjectId = merchant.Id;
                context.MessagePushs.Add(model);
                messages.Add(model.ToDtoObject<message_push_dto>());
            }
        }
        /// <summary>
        /// 平台收入
        /// </summary>
        /// <param name="model">Model.</param>
        /// <param name="amount">Amount.</param>
        /// <param name="merchant_id">Merchant identifier.</param>
        protected void AddMallMerchantAccount(Order order, decimal amount, long merchant_id = 0) {
            var profit = new Profit();
            profit.CreateTime = order.OrderTime;
            profit.PayId = order.PayId;
            profit.OrderId = order.Id;
            profit.ProductId = order.OrderItems.FirstOrDefault().ProductId;
            profit.SkuId = order.OrderItems.FirstOrDefault().SkuId;
            profit.Amount = amount;
            profit.MerchantId = merchant_id;
            profit.BillType = BillType.FeeProfit;
            profit.BillStatus = BillStatus.Proceed;
            profit.Version = 1;
            context.Profits.Add(profit);
            var bill = context.Bills.FirstOrDefault(c => c.MerchantId == merchant_id);
            bill.Deposit += amount;
        }
    }
}
